// Copyright  2004-2008 Backplane Ltd.
//
// This file is part of Ubiquity formsPlayer
//
// Ubiquity formsPlayer is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
//
// Ubiquity formsPlayer is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License
// along with Ubiquity formsPlayer If not, see <http://www.gnu.org/licenses/>.
//	
//
//   Purpose: implementation of CXFormsElementSelectMany.
//   $Id$
#include "stdafx.h"
#include "XForms.h"
#include "XFormsApp.h"
#include "selectui.h"
#include "parseSelection.h"

CXFormsElementSelectMany::CXFormsElementSelectMany()
{
	m_bMultiselectAllowed = true;
}

CXFormsElementSelectMany::~CXFormsElementSelectMany()
{

}

CXFormsElementSelectOne::CXFormsElementSelectOne()
:m_didResize(0)
{
	m_bMultiselectAllowed = false;
}

CXFormsElementSelectOne::~CXFormsElementSelectOne()
{

}

CImpl* CXFormsElementSelectOne::CreateImpl()
{
	CImpl* pFormControl = (CImpl*) new CImplSelectOne(this);

	return pFormControl;
}

CXFormsParse* CXFormsElementSelectOne::CreateParse(CImpl* pImpl)
{
	CXFormsParse* pParse = new CXFormsParseSelectOne((CImplSelectOne*) pImpl);

	return pParse;
}


HRESULT CXFormsElementSelection::AddItem
(
	const BSTR sId,			//ID of the item to put or modify
	const BSTR bsCaption,	//Caption to put
	const BSTR bsValue,		//Value to put
	const BSTR sParentId,	//ID of the choices group to put the item into
	const bool bClear		//Whether to remove all options with that ID (for itemset.)
)
{
	HRESULT hr = E_FAIL;
	if(m_bNewMethod && m_pControlWin)
	{
		VARIANT vt;
		VARIANTARG arr[5];
		CComVariant vtId(sId);
		arr[4] = vtId;
		CComVariant vtCaption(bsCaption);
		arr[3] = vtCaption;
		CComVariant vtValue(bsValue);
		arr[2] = vtValue;
		CComVariant vtParentId(sParentId);
		arr[1] = vtParentId;
		CComVariant vtClear(static_cast<long>(bClear));
		arr[0] = vtClear;
		DISPPARAMS params = {arr,0,5,0};
		if(!strcmp(m_sControlName,"select1-minimal"))
		{
			SetScriptContext();

			hr = UIExecFunction(m_pXForms->m_pSelect1MinimalLibraryDispatch,L"AddItem",&params,&vt,m_didAddItem);

		}
		else
		{
			hr = UIExecFunction(L"AddItem",&params,&vt,m_didAddItem);
		}
	}
	else
	{
		//do nothing  yet.
		hr = E_FAIL;
	}
	
	return hr;
	
}

HRESULT CXFormsElementSelection::put_ItemCaption
(
	const BSTR sId,
	const BSTR bsCaption,
	const unsigned long index
)
{
	HRESULT hr = E_NOTIMPL;
	if(m_pControlWin)
	{
		VARIANT vt;
		VARIANTARG arr[3];
	
		CComVariant vtId(sId);
		arr[2] = vtId;
		CComVariant vtCaption(bsCaption);
		arr[1] = vtCaption;
		CComVariant vtIndex(static_cast<long>(index));
		arr[0] = vtIndex;

		DISPPARAMS params = {arr,0,3,0};
		DISPID did = 0;
		if(!strcmp(m_sControlName,"select1-minimal"))
		{
			SetScriptContext();
			hr = UIExecFunction(m_pXForms->m_pSelect1MinimalLibraryDispatch,L"put_ItemLabel",&params,&vt,did);
		}
		else
		{
			hr = UIExecFunction(L"put_ItemLabel",&params,&vt,did);
		}
	}
	return hr; 

}
HRESULT CXFormsElementSelection::put_ItemValue
(
	const BSTR sId,
	const BSTR bsValue,
	const unsigned long index
)
{
	HRESULT hr = E_NOTIMPL;
	if(m_pControlWin)
	{
		VARIANT vt;
		VARIANTARG arr[3];

		CComVariant vtId(sId);
		arr[2] = vtId;
		CComVariant vtValue(bsValue);
		arr[1] = vtValue;
		CComVariant vtIndex(static_cast<long>(index));
		arr[0] = vtIndex;

		DISPPARAMS params = {arr,0,3,0};
		DISPID did = 0;
		if(!strcmp(m_sControlName,"select1-minimal"))
		{
			SetScriptContext();
			hr = UIExecFunction(m_pXForms->m_pSelect1MinimalLibraryDispatch,L"put_ItemValue",&params,&vt,did);
		}
		else
		{
			hr = UIExecFunction(L"put_ItemValue",&params,&vt,did);
		}
		
	}
	return hr;
}

HRESULT CXFormsElementSelection::SetScriptContext()
{
	CComPtr<IHTMLDocument> pDoc;
	HRESULT hr = GetViewlinkDoc(&pDoc);
	VARIANT vt;
	VARIANTARG arr[2];

	CComVariant vtDoc(pDoc);
	arr[1] = vtDoc;
	CComVariant vtWin(m_pControlWin);
	arr[0] = vtWin;
	DISPPARAMS params = {arr, 0, 2, 0};
	hr = UIExecFunction(m_pXForms->m_pSelect1MinimalLibraryDispatch,L"SetContext",&params,&vt,m_didSetContext);
	return hr;
}



HRESULT CXFormsElementSelection::put_ItemAlert(const BSTR sId, const BSTR bsAlert, const unsigned long index)
{
	HRESULT hr = E_FAIL;
	if(m_pControlWin) {
		VARIANT vt;
		VARIANTARG arr[3];
	
		CComVariant vtId(sId);
		arr[2] = vtId;
		CComVariant vtCaption(bsAlert);
		arr[1] = vtCaption;
		CComVariant vtIndex(static_cast<long>(index));
		arr[0] = vtIndex;

		DISPPARAMS params = {arr, 0, 3, 0};
		DISPID did = 0;
		if(!strcmp(m_sControlName,"select1-minimal"))
		{
			SetScriptContext();
			hr = UIExecFunction(m_pXForms->m_pSelect1MinimalLibraryDispatch,L"put_ItemAlert",&params,&vt,did);
		}
		else
		{
			hr = UIExecFunction(L"put_ItemAlert", &params, &vt,did);
		}
	}
	return hr; 
}


//////////////////////////////////////////////////////////////////////
// CXFormsElementSelection Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CXFormsElementSelection::CXFormsElementSelection()
:m_didAddItem(0)
,m_didSetContext(0)
{

}

CXFormsElementSelection::~CXFormsElementSelection()
{
}

CImpl* CXFormsElementSelection::CreateImpl()
{
	CImpl* pFormControl = (CImpl*) new CImplSelection(this);

	return pFormControl;
}

CXFormsParse* CXFormsElementSelection::CreateParse(CImpl* pImpl)
{
	CXFormsParse* pParse = new CXFormsParseSelection((CImplSelection*) pImpl);

	return pParse;
}

HRESULT CXFormsElementSelection::getUI(CComBSTR &sHtml)
{

	HRESULT hr = S_OK;
	CImplFormControlInput* pFormControl = (CImplFormControlInput*) m_pImpl;

	if (pFormControl)
	{

		//TODO: use CC/PP to lookup preferences.

		if
		(
			//Tree has been turned off.
//			pFormControl->m_sAppearance == "compact"
//			||
			!pFormControl->m_sAppearance 
			||
			pFormControl->m_sAppearance == "minimal"
		)
		{
			if(m_bMultiselectAllowed)
				m_sControlName = "select-minimal";	
			else	
				m_sControlName = "select1-minimal";
		}

		else if
		(
			pFormControl->m_sAppearance == "full"
		)
		{
			if(m_bMultiselectAllowed)
				m_sControlName = "select-full";	
			else	
				m_sControlName = "select1-full";
		}


		else if
		(
			pFormControl->m_sAppearance == "compact"
		)
		{
			if(m_bMultiselectAllowed)
				m_sControlName = "select-compact";	
			else	
				m_sControlName = "select1-compact";
		}

	}
		m_bNewMethod = true;
		//createPath();
		//m_sControlName = "input";
		return CXFormsElement::getUI(sHtml);
}

HRESULT CXFormsElementSelection::put_caption(const BSTR bsCaption)
{
	HRESULT hr = S_FALSE;
	if(m_bNewMethod && m_pControlWin)
	{
		if(!strcmp(m_sControlName,"select1-minimal"))
		{
			SetScriptContext();
			BSTR bsFnName =::SysAllocString(L"put_label");
			CComVariant vtArg(bsCaption);
			DISPPARAMS params = {&vtArg,0,1,0};
			VARIANT vt;
			DISPID didPutLabel = 0;
			HRESULT hr = UIExecFunction(m_pXForms->m_pSelect1MinimalLibraryDispatch,bsFnName,&params,&vt,didPutLabel);
			::SysFreeString(bsFnName);

		}
		else
			hr = __super::put_caption(bsCaption);
	}
	else
	{
		m_sLabel = bsCaption;
	}
	return hr;
}

HRESULT CXFormsElementSelection::put_value(BSTR bsValue)
{
	HRESULT hr = S_FALSE;
	if(m_bNewMethod && m_pControlWin)
	{
		CComVariant vtArg(bsValue);
		DISPPARAMS params = {&vtArg,0,1,0};
		VARIANT vt;
		m_bPuttingValue = true;
		CComBSTR sFuncName(L"put_value");

		if(!strcmp(m_sControlName,"select1-minimal"))
		{
			SetScriptContext();
			hr = UIExecFunction(m_pXForms->m_pSelect1MinimalLibraryDispatch,sFuncName,&params,&vt,m_didPutValue);
		}
		else
		{
			hr = UIExecFunction(sFuncName,&params,&vt,m_didPutValue);
		}
		m_bPuttingValue = false;
		if(m_sLabel)
		{
			put_caption(m_sLabel);
			m_sLabel.Empty();
		}
	}
    return hr;
}

HRESULT CXFormsElementSelection::put_alert(const BSTR bsValue)
{
	
	HRESULT hr = S_FALSE;
	if(m_bNewMethod && m_pControlWin)
	{
		CComVariant vtArg(bsValue);
		DISPPARAMS params = {&vtArg,0,1,0};
		CComVariant vt;
		CComBSTR sFuncName(L"put_alert");

		if(!strcmp(m_sControlName,"select1-minimal"))
		{
			SetScriptContext();
			hr = UIExecFunction(m_pXForms->m_pSelect1MinimalLibraryDispatch,sFuncName,&params,&vt,m_didPutAlert);
		}
		else
		{
			hr = UIExecFunction(sFuncName,&params,&vt,m_didPutAlert);
		}
	}
    return hr;
}


HRESULT CXFormsElementSelectOne::resize()
{
	
	HRESULT hr = S_FALSE;
	if(m_bNewMethod && m_pControlWin)
	{
		DISPPARAMS params = {0,0,0,0};
		CComVariant vt;
		CComBSTR sFuncName(L"resize");

		if(!strcmp(m_sControlName,"select1-minimal"))
		{
			SetScriptContext();
			hr = UIExecFunction(m_pXForms->m_pSelect1MinimalLibraryDispatch,sFuncName,&params,&vt,m_didResize);
		}
	}
    return hr;
}

HRESULT GetParentWindowOfElement(IHTMLElement * pEl, IHTMLWindow2 ** pWin2)
{
	HRESULT hr;
	if(pEl)
	{
		if(pWin2)
		{
			CComPtr<IDispatch> pDispDoc;
			hr = pEl->get_document(&pDispDoc);
			if(pDispDoc)
			{
				CComQIPtr<IHTMLDocument2> pDoc = pDispDoc;
				if(pDoc)
					pDoc->get_parentWindow(pWin2);
			}
		}
		else
			hr = E_POINTER;
	}
	else
	{
		hr = E_INVALIDARG;
	}
	return hr;
}

HRESULT CXFormsElementSelectOne::detachEvents()
{
	try
	{
		if(m_pEventSink)
		{
			CComPtr<IHTMLElement> pMaster;
			if(SUCCEEDED(GetMasterElement(&pMaster)) && pMaster)		
			{
				CComBSTR bs(L"onresize");
				CComPtr<IHTMLWindow2> pWin;
				GetParentWindowOfElement(pMaster,&pWin);
				CComQIPtr<IHTMLWindow3> pWin3 = pWin;
				if(pWin3)
					pWin3->detachEvent(bs, m_pEventSink);
			}
		}
	}
	catch(...)
	{
	}

	return __super::detachEvents();
}

HRESULT CXFormsElementSelectOne::ElementReady()
{
	HRESULT hr = __super::ElementReady();
	CComPtr<IHTMLElement> pMaster;
	hr = GetMasterElement(&pMaster);
	if(SUCCEEDED(hr) && m_pEventSink)		
	{
		VARIANT_BOOL b;
		CComBSTR bs(L"onresize");
		CComPtr<IHTMLWindow2> pWin;
		GetParentWindowOfElement(pMaster,&pWin);
		CComQIPtr<IHTMLWindow3> pWin3(pWin);
		hr = pWin3->attachEvent(bs,m_pEventSink,&b);
	}
	return hr;
}

HRESULT CXFormsElementSelectOne::handleEvent(CComBSTR& sEventName, IHTMLEventObj2 * pEventObject,VARIANT * pvarResult)
{
	HRESULT hr;
	if(sEventName  == L"resize")
	{
		hr = resize();
	}
	else
		hr = __super::handleEvent(sEventName,pEventObject,pvarResult);
	return hr;
}


STDMETHODIMP CXFormsElementSelection::get_CurrentValue(BSTR *psCurrentValue)
{
	HRESULT hr = S_OK;

	if(psCurrentValue)
	{
		if(m_pControlElement)
		{
			CComVariant vt;
			BSTR bs = ::SysAllocString(L"AbsoluteIndexValue");
			m_pControlElement->getAttribute(bs,2,&vt);
			::SysFreeString(bs);
			if(vt.vt == VT_BSTR)
			{
				*psCurrentValue = ::SysAllocString(vt.bstrVal);
			}
			else if(vt.vt == VT_I4)
			{
				//convert the number to an appropriate string.
				hr = S_FALSE;
			}
			else
			{
				*psCurrentValue = 0;
			}
			//HACK: need to add attributes to the masterElement without changing the IDL
			//	
			CComPtr<IHTMLElement> pMaster;
			GetMasterElement(&pMaster);
			if(pMaster)
			{
				CComBSTR sSelectionValueLabel(L"CurrentSelectionValueLabel");
				CComVariant vtValueLabel;
				m_pControlElement->getAttribute(sSelectionValueLabel,2,&vtValueLabel);
				pMaster->setAttribute(sSelectionValueLabel,vtValueLabel);
				CComBSTR sSelectionValue(L"CurrentSelectionValue");
				CComVariant vtValue;
				m_pControlElement->getAttribute(sSelectionValue,2,&vtValue);
				pMaster->setAttribute(sSelectionValue,vtValue);
			}
		}
		
/*		if(pSelection->m_sCurrentValueAsText.Length() > 0)
			*psCurrentValue = m_sCurrentValue.Copy();
		else
			hr = S_FALSE;
*/	}
	else
		hr = E_POINTER;

	return hr;
}